﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Yunwei.WinSocket.Server
{
    public partial class Form1 : Form
    {
        int port = 9999;
        string host = "127.0.0.1";
        Socket socket;
        Dictionary<string, Socket> dictSocket = new Dictionary<string, Socket>();
        Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();

        Action<string> setMessageDelegate;
        public Form1()
        {
            InitializeComponent();
            setMessageDelegate = new Action<string>(setMessage);
            this.FormClosed += Form1_FormClosed;
        }

        void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
            foreach (var s in dictSocket)
            {
                if (s.Value.Connected)
                {
                    s.Value.Shutdown(SocketShutdown.Both);
                    s.Value.Close();
                }
            }
        }

        private void btnListen_Click(object sender, EventArgs e)
        {
            IPAddress ipAddress = IPAddress.Parse(host);
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port);

            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Bind(ipEndPoint);

            socket.Listen(10);
            tbMessage.Text = "等待客户端链接\n";

            Thread thread = new Thread(watchConnecting);
            thread.IsBackground = true;
            thread.Start();
            tbMessage.Text = "服务器监听启动\r\n";

            System.Timers.Timer timer = new System.Timers.Timer(5000);
            timer.Elapsed += timer_Elapsed;
            timer.Start();
        }

        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (dictSocket.Count == 0)
                return;

            string msg = "1|2|3|4";//"我是轮询:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n";
            byte[] msgByte = Encoding.UTF8.GetBytes(msg);

            foreach (var s in dictSocket)
            {
                if (s.Value.Connected)
                    s.Value.Send(msgByte);
            }
        }

        private void watchConnecting()
        {
            while (true)
            {
                Socket socketConnection = socket.Accept();

                setMessageDelegate("客户端" + socketConnection.RemoteEndPoint.ToString() + "已连接\r\n");
                dictSocket.Add(socketConnection.RemoteEndPoint.ToString(), socketConnection);

                Thread threadRecv = new Thread(receivMessage);
                threadRecv.IsBackground = true;
                threadRecv.Start(socketConnection);

                dictThread.Add(socketConnection.RemoteEndPoint.ToString(), threadRecv);
            }
        }

        private void receivMessage(object socketConnection)
        {
            Socket socketClient = socketConnection as Socket;
            while (socketClient.Connected)
            {
                try
                {
                    if (socketClient.Connected)
                    {
                        byte[] byteMessage = new byte[1024 * 1024 * 2];
                        int length = -1;

                        length = socketClient.Receive(byteMessage);

                        string message = Encoding.UTF8.GetString(byteMessage);
                        setMessageDelegate(message);
                    }
                    else
                    {
                    }
                }
                catch (Exception ex)
                {
                    dictSocket.Remove(socketClient.RemoteEndPoint.ToString());
                    dictThread.Remove(socketClient.RemoteEndPoint.ToString());

                    setMessage(ex.Message);
                }
            }

            dictSocket.Remove(socketClient.RemoteEndPoint.ToString());
            dictThread.Remove(socketClient.RemoteEndPoint.ToString());
        }
        
        private void setMessage(string msg)
        {
            if (tbMessage.InvokeRequired)
            {
                tbMessage.Invoke(setMessageDelegate, msg);
            }
            else
            {
                tbMessage.AppendText(msg);
            }
        }
    }
}
